Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GameScope: Fix blank GSSHWRES and GSINTRES displaying 'x' #1154

Merged

Conversation

sonic2kk
Copy link
Owner

Overview

When GSSHWRES or GSINTRES were left blank, this would result in the boxes displaying 'x'. This was brought up in #1152, and some implementation discussion went on there. This is fixed by parsing the value for -W/-H and -w/-h using getGameScopeArg, and by refactoring getGameScopeArg to accommodate this.

This PR also flattens getGameScopeArg a bit as well, to reduce nesting and improve readibility.

Background

The reason for this bug is that we were only checking if the width and height flags (-w/-h/-W/-H) were defined, but not if they contained values. We incorrectly assumed that if the flags were present they would also have values, which is not the case.

As a result, we would fall into the else block when setting these resolutions and run GSINTRES="$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -wA1 "\-w" | tail -n1)x$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -wA1 "\-h" | tail -n1)" and GSSHWRES="$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -wA1 "\-W" | tail -n1)x$(tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -wA1 "\-H" | tail -n1)". However the logic to parse out the width and height would return garbage, because there was no numeric value to parse out. Instead, it would parse out the next flag after it, or if it was the last flag in the arguments list, it would just print that flag. So if we passed -W and -H, GSSHWRES would end up returning -Hx-H, because -H comes after -W, and -H is the last flag so for the height value it just returns itself.

This code snippet should illustrate the problem:

# This will return `-h`
GAMESCOPE_ARGS="-w -h"
tr ' ' '\n' <<< "$GAMESCOPE_ARGS" | grep -wA1 "\-w" | tail -n1)

The reason the dropdown would display x and not -Hx-H or -hx-h is because we have some logic to only display integers on this Yad UI element:

--field="$GUI_GSINTRES!$DESC_GSINTRES ('GSINTRES')":CBE "$(cleanDropDown "${GSINTRES//\"}" "$(printf "%s\n" "$("$XRANDR" --current | grep "[0-9]x" | awk '{print $1}' | grep "^[0-9]" | tr '\n' '!')")")" \
--field="$GUI_GSSHWRES!$DESC_GSSHWRES ('GSSHWRES')":CBE "$(cleanDropDown "${GSSHWRES//\"}" "$(printf "%s\n" "$("$XRANDR" --current | grep "[0-9]x" | awk '{print $1}' | grep "^[0-9]" | tr '\n' '!')")")" \

This is how we end up with x, that logic removes the -Hx-H/-hx-h.

Solution

The fix is to ensure that when we're parsing the resolution values, we should ignore any values that are not numeric. So if we get, for example, -H as our value, we should assume this is invalid and fall back to the default 1280x720. Even if one of the values is wrong, we should invalidate the entire resolution and default back.

In order to do this, I ended up with a messy solution that would be duplicated for both resolutions that we capture. A cleaner way would be to have a re-usable function, and ultimately that led me to deciding to use getGameScopeArg for this. Back when this was implemented during one of the GameScope refactors, I did not initially opt to use this for the GameScope resolutions as it was a bit tricky. However now it is possible and it worked out of the box by just using it as a drop-in replacement to capture the internal and show resolutions!

But sadly that victory was short lived and I found out getGameScopeArg has the same limitation as the existing logic, in that it also returned x (or actually, -hx-h/-Hx-H). It had the same behaviour as our existing logic. So getGameScopeArg needed a refactor.

The change I made was that when we're expecting getGameScopeArg to parse out a NUM value, we should check that the value we parse out is actually a number. Since this could be an integer value or a decimal value, we need to account for both. So we can use this regex to do so: grep -P "^([\d]+)(?:\.([\d]{1,2}?))?$". If we apply this regex to the garbage output of -w -h, which will return -h, we will get an empty string. When we get this we can default to returning the default value, which is specified as 1280 for width and 720 for height when we call getGameScopeArg.

# GameScope Show Resolution (corresponds to -W, -H options, uppercase) -- Actual GameScope window size (defaults to 1280x720) -- Dropdown
# Although this is a combobox, we still use "num" as the `getGameScopeArg` type because we want numeric validation
GSSHOWRESARGWIDTH="$( getGameScopeArg "$GAMESCOPE_ARGS" "-W" "$GSSHOWRESARGWIDTH" "" "1280" "num")"
GSSHOWRESARGHEIGHT="$( getGameScopeArg "$GAMESCOPE_ARGS" "-H" "$GSSHOWRESARGHEIGHT" "" "720" "num")"

GSSHWRES="${GSSHOWRESARGWIDTH}x${GSSHOWRESARGHEIGHT}"

# GameScope Internal Resolution (corresponds to -w, -h options, lowercase) -- Resolution that games see (defaults to 1280x720) -- Dropdown
# Although this is a combobox, we still use "num" as the `getGameScopeArg` type because we want numeric validation
GSINTRESARGWIDTH="$( getGameScopeArg "$GAMESCOPE_ARGS" "-W" "$GSINTRESARGWIDTH" "" "1280" "num")"
GSINTRESARGHEIGHT="$( getGameScopeArg "$GAMESCOPE_ARGS" "-H" "$GSINTRESARGHEIGHT" "" "720" "num")"

GSINTRES="${GSINTRESARGWIDTH}x${GSINTRESARGHEIGHT}"

This change allows us to correctly handle cases where the width and height flag are given, but do not return numeric values (resolution can only be numeric). Refactoring this in getGameScopeArg allows us to re-use this function for setting the GameScope resolutions finally and also means anywhere else in the GameScope logic that may have been impacted by this will also benefit from this fix. (I don't think anywhere else was impacted, but it is still good to have this logic contained in one place).

Remaining Work

Since this is a change to getGameScopeArg we need to make sure this fix works correctly. I did some testing before opening a PR and values for comboboxes and numeric values seem to still save correctly, but this will need extensive testing before it can be merged.

Future Work

GameScope does allow you to simply pass the -h or -H flags, and it will calculate a 16:9 resolution based on the height alone (GameScope assumes 16:9 if not specified, which is why I am proposing that we default to 16:9 as well, to match GameScope behaviour). Perhaps in future in SteamTinkerLaunch we can check if we have a height value, and calculate an appropriate width if it is blank. We could do this by checking if [ -z "${GSINTRESARGWIDTH}" ] && [ -n "${GSINTRESARGHEIGHT}" ]" and then assigning a width value to GSINTRESARGWIDTH`.

This would really only be useful for users that manually enter a GameScope arguments string into the Game Menu or their Per-Game Config File, as -h 1080 -- is valid and GameScope would recognise this, but SteamTinkerLaunch would not.

This potential future work would not really apply to the GameScope menu and would probably not benefit it in any significant way, unless x1080 would actually parse out the height and store it but not the width. We could consider this in future though I suppose.


The remaining work here is to test this thoroughly. It fixes the bug it set out to fix but we need to regression test :-)

@sonic2kk sonic2kk force-pushed the gamescope-use-getgamescopearg-for-gsshwres-gsintres branch from ea827de to 8464c94 Compare August 28, 2024 23:10
@HanPrower
Copy link
Contributor

After a quick fumble, whilst the dropdowns are now falling back when empty (or not a number) correctly, if you clear the option click Done and then open the GAME MENU you get:
-w -h -W -H --

Just needs extra logic that if it's not set to throw it away? :)

Also when clicking Done if the box isn't valid (i.e. filled with quite literally "junk") it doesn't verify it.

@sonic2kk
Copy link
Owner Author

Yeah, we can probably discard the flags if they have no value assigned. We do that for other flags but I guess we don't for the resolutions for some reason.

Also when clicking Done if the box isn't valid (i.e. filled with quite literally "junk") it doesn't verify it.

Are you saying we should validate that the resolution values are only numeric when clicking "Done"? If so, that isn't a bug, that's just not implemented. We could do it, though.

@sonic2kk
Copy link
Owner Author

With 03749b9, the internal and show resolutions should not be appended to the GAMESCOPE_ARGS if the width and height values are blank. I also left a comment for potential future work of calculating a 16:9 aspect ratio if only the -h flag is given. Although that's probably more useful when opening the GameScope menu where a user may have entered -h 720, but conceivably could be done on our GameScope GUI menu by typing x720. We technically don't even need to write out the -w value because GameScope doesn't need it, but we would want to calculate it for display purposes so that we could display 1280x720 instead of x720.

I am not sure yet if we should validate the text boxes. This is an odd case, as any other free text field can be just that, free text, and it's on the user if they get it wrong. But in this instance we are using a text field to accept numerical number input. I'll leave it up to you, since you suggested it. I think this change should be fairly straightforward, and we can use even simpler regex since resolutions should not be decimals so we can just use regex to parse out anything that isn't an integer when we get the parsed out separate width and height variables.

If we do go that route with that kind of validation,we could probably also force the resolution values to be lowercase, so that we don't misinterpret 1280X720 for example. We can probably do that with "${GSARR[$GSGENERALHEADING + 1],,}".

@HanPrower
Copy link
Contributor

Nah, it doesn't need changing. It was just an observation, but it's fine to trust the users and programs to handle things properly (or to throw their own errors).

The latest commit seems to be having issues:
grep: warning: stray \ before -

@sonic2kk
Copy link
Owner Author

sonic2kk commented Aug 30, 2024

grep: warning: stray \ before -

This has always been spammed with GameScope, is it breaking anything? If not, then it can be safely ignored.

It happens on most SteamTinkerLaunch menus to my knowledge, even the Game Menu.

@sonic2kk
Copy link
Owner Author

Need to test this with an actual game to make sure things still work as expected, and then this can be merged. Hopefully after a long sleep and some much-needed afternoon coffee I'll get around to testing and merging this.

Now that GAMESCOPE_ARGS is not guaranteed to have any values,
GAMESCOPE_ARGS can be blank when appending flags, so we should
remove trailing whitespaces.

This should be purely cosmetic.
Messed up the casing, jeez... I need more coffee.
@sonic2kk sonic2kk force-pushed the gamescope-use-getgamescopearg-for-gsshwres-gsintres branch from 87d3b45 to 758711a Compare September 3, 2024 21:34
@sonic2kk
Copy link
Owner Author

sonic2kk commented Sep 3, 2024

Tested with Cookie Clicker, both options work as expected. If not defined, they will default on write to 1280x720 and this takes effect as expected on game launch.

If these are modified on the Main Menu, in the gamescope args section, I assume things don't work, as this is a "raw" way to edit the GameScope arguments.

This is good to be merged after a version bump.

@sonic2kk sonic2kk merged commit 70d9fea into master Sep 3, 2024
2 checks passed
@sonic2kk sonic2kk deleted the gamescope-use-getgamescopearg-for-gsshwres-gsintres branch September 3, 2024 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants